home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mint110s / biosfs.c < prev    next >
C/C++ Source or Header  |  1994-02-11  |  43KB  |  1,873 lines

  1. /*
  2. Copyright 1991,1992 Eric R. Smith.
  3. Copyright 1993,1994 Atari Corporation.
  4. All rights reserved.
  5.  */
  6.  
  7. /* simple biosfs.c */
  8.  
  9. #include "mint.h"
  10.  
  11. extern struct kerinfo kernelinfo;    /* see main.c */
  12.  
  13. static long    ARGS_ON_STACK bios_root    P_((int drv, fcookie *fc));
  14. static long    ARGS_ON_STACK bios_lookup    P_((fcookie *dir, const char *name, fcookie *fc));
  15. static long    ARGS_ON_STACK bios_getxattr    P_((fcookie *fc, XATTR *xattr));
  16. static long    ARGS_ON_STACK bios_chattr    P_((fcookie *fc, int attrib));
  17. static long    ARGS_ON_STACK bios_chown    P_((fcookie *fc, int uid, int gid));
  18. static long    ARGS_ON_STACK bios_chmode    P_((fcookie *fc, unsigned mode));
  19. static long    ARGS_ON_STACK bios_rmdir    P_((fcookie *dir, const char *name));
  20. static long    ARGS_ON_STACK bios_remove    P_((fcookie *dir, const char *name));
  21. static long    ARGS_ON_STACK bios_getname    P_((fcookie *root, fcookie *dir, char *pathname, int size));
  22. static long    ARGS_ON_STACK bios_rename    P_((fcookie *olddir, char *oldname,
  23.                     fcookie *newdir, const char *newname));
  24. static long    ARGS_ON_STACK bios_opendir    P_((DIR *dirh, int flags));
  25. static long    ARGS_ON_STACK bios_readdir    P_((DIR *dirh, char *nm, int nmlen, fcookie *fc));
  26. static long    ARGS_ON_STACK bios_rewinddir    P_((DIR *dirh));
  27. static long    ARGS_ON_STACK bios_closedir    P_((DIR *dirh));
  28. static long    ARGS_ON_STACK bios_pathconf    P_((fcookie *dir, int which));
  29. static long    ARGS_ON_STACK bios_dfree    P_((fcookie *dir, long *buf));
  30. static DEVDRV *    ARGS_ON_STACK bios_getdev    P_((fcookie *fc, long *devspecial));
  31. static long    ARGS_ON_STACK bios_fscntl    P_((fcookie *, const char *, int, long));
  32. static long    ARGS_ON_STACK bios_symlink    P_((fcookie *, const char *, const char *));
  33. static long    ARGS_ON_STACK bios_readlink    P_((fcookie *, char *, int));
  34.  
  35. static long    ARGS_ON_STACK bios_topen    P_((FILEPTR *f));
  36. static long    ARGS_ON_STACK bios_twrite    P_((FILEPTR *f, const char *buf, long bytes));
  37. static long    ARGS_ON_STACK bios_tread    P_((FILEPTR *f, char *buf, long bytes));
  38. static long    ARGS_ON_STACK bios_nwrite    P_((FILEPTR *f, const char *buf, long bytes));
  39. static long    ARGS_ON_STACK bios_nread    P_((FILEPTR *f, char *buf, long bytes));
  40. static long    ARGS_ON_STACK bios_ioctl    P_((FILEPTR *f, int mode, void *buf));
  41. static long    ARGS_ON_STACK bios_select    P_((FILEPTR *f, long p, int mode));
  42. static void    ARGS_ON_STACK bios_unselect    P_((FILEPTR *f, long p, int mode));
  43. static long    ARGS_ON_STACK bios_tseek    P_((FILEPTR *f, long where, int whence));
  44. static long    ARGS_ON_STACK bios_close    P_((FILEPTR *f, int pid));
  45.  
  46. long    ARGS_ON_STACK null_open    P_((FILEPTR *f));
  47. long    ARGS_ON_STACK null_write    P_((FILEPTR *f, const char *buf, long bytes));
  48. long    ARGS_ON_STACK null_read    P_((FILEPTR *f, char *buf, long bytes));
  49. long    ARGS_ON_STACK null_lseek    P_((FILEPTR *f, long where, int whence));
  50. long    ARGS_ON_STACK null_ioctl    P_((FILEPTR *f, int mode, void *buf));
  51. long    ARGS_ON_STACK null_datime    P_((FILEPTR *f, short *time, int rwflag));
  52. long    ARGS_ON_STACK null_close    P_((FILEPTR *f, int pid));
  53. long    ARGS_ON_STACK null_select    P_((FILEPTR *f, long p, int mode));
  54. void    ARGS_ON_STACK null_unselect    P_((FILEPTR *f, long p, int mode));
  55.  
  56. static long ARGS_ON_STACK mouse_open    P_((FILEPTR *f));
  57. static long ARGS_ON_STACK mouse_read    P_((FILEPTR *f, char *buf, long nbytes));
  58. static long ARGS_ON_STACK mouse_ioctl P_((FILEPTR *f, int mode, void *buf));
  59. static long ARGS_ON_STACK mouse_close P_((FILEPTR *f, int pid));
  60. static long ARGS_ON_STACK mouse_select P_((FILEPTR *f, long p, int mode));
  61. static void ARGS_ON_STACK mouse_unselect P_((FILEPTR *f, long p, int mode));
  62.  
  63. /* device driver for BIOS terminals */
  64.  
  65. DEVDRV bios_tdevice = {
  66.     bios_topen, bios_twrite, bios_tread, bios_tseek, bios_ioctl,
  67.     null_datime, bios_close, bios_select, bios_unselect
  68. };
  69.  
  70. /* device driver for BIOS devices that are not terminals */
  71.  
  72. DEVDRV bios_ndevice = {
  73.     null_open, bios_nwrite, bios_nread, null_lseek, bios_ioctl,
  74.     null_datime, bios_close, bios_select, bios_unselect
  75. };
  76.  
  77. DEVDRV null_device = {
  78.     null_open, null_write, null_read, null_lseek, null_ioctl,
  79.     null_datime, null_close, null_select, null_unselect
  80. };
  81.  
  82. DEVDRV mouse_device = {
  83.     mouse_open, null_write, mouse_read, null_lseek, mouse_ioctl,
  84.     null_datime, mouse_close, mouse_select, mouse_unselect
  85. };
  86.  
  87. /* this special driver is checked for in dosfile.c, and indicates that
  88.  * a dup operation is actually wanted rather than an open
  89.  */
  90. DEVDRV fakedev;
  91.  
  92. #ifdef FASTTEXT
  93. extern DEVDRV screen_device;    /* see fasttext.c */
  94. #endif
  95.  
  96. FILESYS bios_filesys = {
  97.     (FILESYS *)0,
  98.     FS_LONGPATH,
  99.     bios_root,
  100.     bios_lookup, nocreat, bios_getdev, bios_getxattr,
  101.     bios_chattr, bios_chown, bios_chmode,
  102.     nomkdir, bios_rmdir, bios_remove, bios_getname, bios_rename,
  103.     bios_opendir, bios_readdir, bios_rewinddir, bios_closedir,
  104.     bios_pathconf, bios_dfree, nowritelabel, noreadlabel,
  105.     bios_symlink, bios_readlink, nohardlink, bios_fscntl, nodskchng
  106. };
  107.  
  108.  
  109. struct tty con_tty, aux_tty, midi_tty;
  110. struct tty sccb_tty, scca_tty, ttmfp_tty;
  111.  
  112. struct bios_file BDEV[] = {
  113.  
  114. /* "real" bios devices present on all machines */
  115.     {"centr", &bios_ndevice, 0, 0, 0, 0},
  116.     {"console", &bios_tdevice, 2, O_TTY, &con_tty, 0},
  117.     {"midi", &bios_tdevice, 3, O_TTY, &midi_tty, 0},
  118.     {"kbd", &bios_ndevice, 4, 0, 0, 0},
  119. /* devices that duplicate handles */
  120.     {"prn", &fakedev, -3, 0, 0, 0}, /* handle -3 (printer) */
  121.     {"aux", &fakedev, -2, 0, 0, 0}, /* handle -2 (aux. terminal) */
  122.     {"con", &fakedev, -1, 0, 0, 0}, /* handle -1 (control terminal) */
  123.     {"tty", &fakedev, -1, 0, 0, 0}, /* the Unix name for it */
  124.     {"stdin", &fakedev, 0, 0, 0, 0},  /* handle 0 (stdin) */
  125.     {"stdout", &fakedev, 1, 0, 0, 0}, /* handle 1 (stdout) */
  126.     {"stderr", &fakedev, 2, 0, 0, 0}, /* handle 2 (stderr) */
  127.     {"fd", &fakedev, S_IFDIR, 0, 0, 0}, /* file descriptor directory */
  128.  
  129. /* other miscellaneous devices */
  130.     {"mouse", &mouse_device, 0, 0, 0, 0},
  131.     {"null", &null_device, 0, 0, 0, 0},
  132.  
  133. #ifdef FASTTEXT
  134. /* alternate console driver */
  135.     {"fasttext", &screen_device, 2, O_TTY, &con_tty, 0},
  136. #endif
  137.  
  138. /* serial port things *must* come last, because not all of these
  139.  * are present on all machines (except for modem1, which does however
  140.  * have a different device number on TTs and STs)
  141.  */
  142.     {"modem1", &bios_tdevice, 6, O_TTY, &aux_tty, 0},
  143.     {"modem2", &bios_tdevice, 7, O_TTY, &sccb_tty, 0},
  144.     {"serial1", &bios_tdevice, 8, O_TTY, &ttmfp_tty, 0},
  145.     {"serial2", &bios_tdevice, 9, O_TTY, &scca_tty, 0},
  146.     {"", 0, 0, 0, 0, 0}
  147. };
  148.  
  149. /* Does the fcookie fc refer to the \dev\fd directory? */
  150. #define IS_FD_DIR(fc) ((fc)->aux == S_IFDIR)
  151. /* Does the fcookie fc refer to a file in the \dev\fd directory? */
  152. #define IS_FD_ENTRY(fc) ((fc)->index > 0 && (fc)->index <= MAX_OPEN-MIN_HANDLE)
  153.  
  154. struct bios_file *broot, *bdevlast;
  155.  
  156. /* a file pointer for BIOS device 1, provided only for insurance
  157.  * in case a Bconmap happens and we can't allocate a new FILEPTR;
  158.  * in most cases, we'll want to build a FILEPTR in the usual
  159.  * way.
  160.  */
  161.  
  162. FILEPTR *defaultaux;
  163.  
  164. /* ts: a xattr field used for the root directory, 'cause there's no
  165.  * bios_file structure for it.
  166.  */
  167. XATTR rxattr;
  168. XATTR fdxattr;
  169.  
  170. /* ts: a small utility function to set up a xattr structure
  171.  */
  172.  
  173. static void set_xattr P_((XATTR *xp, ushort mode, int rdev));
  174.  
  175. void set_xattr(xp, mode, rdev)
  176.     XATTR *xp;
  177.     ushort mode;
  178.     int rdev;
  179. {
  180.     xp->mode = mode;
  181.     xp->index = 0L;
  182.     xp->dev = BIOSDRV;
  183.     xp->rdev = rdev;
  184.     xp->nlink = 1;
  185.     xp->uid = curproc->euid;
  186.     xp->gid = curproc->egid;
  187.     xp->size = 0L;
  188.     xp->blksize = 1L;
  189.     xp->nblocks = 0L;
  190.  
  191.     xp->mtime = xp->atime = xp->ctime = timestamp;
  192.     xp->mdate = xp->adate = xp->cdate = datestamp;
  193.  
  194. /* root directory only */
  195.     if ((mode & S_IFMT) == S_IFDIR)
  196.         xp->attr = FA_DIR;
  197.     else
  198.         xp->attr = 0;
  199.     xp->reserved2 = 0;
  200.     xp->reserved3[0] = 0L;
  201.     xp->reserved3[1] = 0L;
  202. }
  203.  
  204. void
  205. biosfs_init()
  206. {
  207.     struct bios_file *b;
  208.     int majdev, mindev;
  209.  
  210.     broot = BDEV;
  211.  
  212.     for (b = broot; b->name[0]; b++) {
  213.         b->next = b+1;
  214.  
  215.     /* if not a TT or Mega STE, adjust the MODEM1 device to be BIOS
  216.      * device 1
  217.      * and ignore the remaining devices, since they're not present
  218.      */
  219.         if (!has_bconmap && b->private == 6) {
  220.             b->private = 1;
  221.             b->next = 0;
  222.             break;
  223.         }
  224.     /* SERIAL2 is not present on the Mega STe or Falcon */
  225.         if (mch != TT && b->private == 8) {
  226.             b->next = 0;
  227.             break;
  228.         }
  229.             
  230.     }
  231.     bdevlast = b;
  232.     if (b->name[0] == 0) {
  233.         --b;
  234.         b->next = 0;
  235.     }
  236.     defaultaux = new_fileptr();
  237.     defaultaux->links = 1;        /* so it never gets freed */
  238.     defaultaux->flags = O_RDWR;
  239.     defaultaux->pos = 0;
  240.     defaultaux->devinfo = 0;
  241.     defaultaux->fc.fs = &bios_filesys;
  242.     defaultaux->fc.index = 0;
  243.     defaultaux->fc.aux = 1;
  244.     defaultaux->fc.dev = BIOSDRV;
  245.     defaultaux->dev = &bios_ndevice;
  246.  
  247. /* set up XATTR fields */
  248.     set_xattr(&rxattr, S_IFDIR|DEFAULT_DIRMODE, BIOSDRV);
  249.     set_xattr(&fdxattr, S_IFDIR|DEFAULT_DIRMODE, BIOSDRV);
  250.  
  251.     for (b = BDEV; b; b = b->next) {
  252.         if (b->device == &bios_ndevice || b->device == &bios_tdevice) {
  253.             majdev = BIOS_RDEV;
  254.             mindev = b->private;
  255.         } else if (b->device == &fakedev) {
  256.             majdev = FAKE_RDEV;
  257.             mindev = b->private;
  258.         } else {
  259.             majdev = UNK_RDEV;
  260.             mindev = b->private;
  261.         }
  262.         set_xattr(&b->xattr, S_IFCHR|DEFAULT_MODE,
  263.               majdev | (mindev & 0x00ff) );
  264.     }
  265. }
  266.  
  267. static long ARGS_ON_STACK 
  268. bios_root(drv, fc)
  269.     int drv;
  270.     fcookie *fc;
  271. {
  272.     if (drv == BIOSDRV) {
  273.         fc->fs = &bios_filesys;
  274.         fc->dev = drv;
  275.         fc->index = 0L;
  276.         return 0;
  277.     }
  278.     fc->fs = 0;
  279.     return EINTRN;
  280. }
  281.  
  282. static long ARGS_ON_STACK 
  283. bios_lookup(dir, name, fc)
  284.     fcookie *dir;
  285.     const char *name;
  286.     fcookie *fc;
  287. {
  288.     struct bios_file *b;
  289.  
  290.     if (dir->index != 0) {
  291.     /* check for \dev\fd directory */
  292.         if (!IS_FD_DIR(dir)) {
  293.             DEBUG(("bios_lookup: bad directory"));
  294.             return EPTHNF;
  295.         }
  296.         if (!*name || (name[0] == '.' && name[1] == 0)) {
  297.             *fc = *dir;
  298.             return 0;
  299.         }
  300.         if (!strcmp(name, "..")) {
  301.         /* root directory */
  302.             fc->fs = &bios_filesys;
  303.             fc->dev = dir->dev;
  304.             fc->index = 0L;
  305.             return 0;
  306.         }
  307.         if (isdigit(*name) || *name == '-') {
  308.             int fd = (int) atol(name);
  309.             if (fd >= MIN_HANDLE && fd < MAX_OPEN) {
  310.                 fc->fs = &bios_filesys;
  311.                 fc->dev = dir->dev;
  312.                 fc->aux = fd;
  313.                 fc->index = fd - MIN_HANDLE + 1;
  314.                 return 0;
  315.             }
  316.         }
  317.         DEBUG(("bios_lookup: name (%s) not found", name));
  318.         return EFILNF;
  319.     }
  320.  
  321. /* special case: an empty name in a directory means that directory */
  322. /* so does "." */
  323.     if (!*name || (name[0] == '.' && name[1] == 0)) {
  324.         *fc = *dir;
  325.         return 0;
  326.     }
  327.  
  328. /* another special case: ".." could be a mount point */
  329.     if (!strcmp(name, "..")) {
  330.         *fc = *dir;
  331.         return EMOUNT;
  332.     }
  333.  
  334.     for (b = broot; b; b = b->next) {
  335.         if (!stricmp(b->name, name)) {
  336.             fc->fs = &bios_filesys;
  337.             fc->index = (long)b;
  338.             fc->aux = b->private;
  339.             fc->dev = dir->dev;
  340.             return 0;
  341.         }
  342.     }
  343.     DEBUG(("bios_lookup: name(%s) not found", name));
  344.     return EFILNF;
  345. }
  346.  
  347. static long ARGS_ON_STACK 
  348. bios_getxattr(fc, xattr)
  349.     fcookie *fc;
  350.     XATTR *xattr;
  351. {
  352.     FILEPTR *f;
  353.     struct bios_file *b = (struct bios_file *)fc->index;
  354.     long r;
  355.     int majdev, mindev;
  356.  
  357.     majdev = UNK_RDEV;
  358.     mindev = 0;
  359.  
  360.     if (fc->index == 0) {            /* root directory? */
  361.         *xattr = rxattr;
  362.         xattr->index = fc->index;
  363.         xattr->dev = fc->dev;
  364.     } else if (IS_FD_DIR(fc)) {        /* fd directory? */
  365.         *xattr = fdxattr;
  366.         xattr->index = fc->index;
  367.         xattr->dev = fc->dev;
  368.     } else if (IS_FD_ENTRY(fc)) {
  369.         /* u:\dev\fd\n */
  370.         f = curproc->handle[(int)fc->aux];
  371.         if (f) {
  372.             r = (*f->fc.fs->getxattr)(&f->fc, xattr);
  373.             if (r < 0)
  374.                 return r;
  375.         } else {
  376.             majdev = FAKE_RDEV;
  377.             mindev = ((int)fc->aux) & 0x00ff;
  378.             set_xattr(xattr, S_IFCHR | DEFAULT_MODE, majdev|mindev);
  379.         }
  380.     } else if (b->device == &fakedev) {
  381.         if ((f = curproc->handle[b->private]) != 0) {
  382.             /* u:\dev\stdin, u:\dev\stdout, etc. */
  383.             r = (*f->fc.fs->getxattr) (&f->fc, xattr);
  384.             if (r < 0) return r;
  385.         } else {
  386.             majdev = FAKE_RDEV;
  387.             mindev = ((int)b->private) & 0x00ff;
  388.             set_xattr(xattr, S_IFCHR|DEFAULT_MODE, majdev|mindev);
  389.         }
  390.     } else {
  391.         *xattr = b->xattr;
  392.         xattr->index = fc->index;
  393.         xattr->dev = fc->dev;
  394.     }
  395.     return 0;
  396. }
  397.  
  398. static long ARGS_ON_STACK 
  399. bios_chattr(fc, attrib)
  400.     fcookie *fc;
  401.     int attrib;
  402. {
  403.     UNUSED(fc); UNUSED(attrib);
  404.     return EACCDN;
  405. }
  406.  
  407. static long ARGS_ON_STACK 
  408. bios_chown(fc, uid, gid)
  409.     fcookie *fc;
  410.     int uid, gid;
  411. {
  412.     struct bios_file *b = (struct bios_file *)fc->index;
  413.  
  414.     if (!(curproc->euid)) {
  415.         if (!b) {
  416.             /* a directory */
  417.             rxattr.uid = uid;
  418.             rxattr.gid = gid;
  419.         } else if (IS_FD_DIR(fc)) {
  420.             fdxattr.uid = uid;
  421.             fdxattr.gid = gid;
  422.         } else if (!IS_FD_ENTRY(fc)) {
  423.             /* any other entry */
  424.             b->xattr.uid = uid;
  425.             b->xattr.gid = gid;
  426.         }
  427.         return 0;
  428.     }
  429.  
  430.     return EACCDN;
  431. }
  432.  
  433. static long ARGS_ON_STACK 
  434. bios_chmode(fc, mode)
  435.     fcookie *fc;
  436.     unsigned mode;
  437. {
  438.     struct bios_file *b = (struct bios_file *)fc->index;
  439.  
  440.     if (!b) {
  441.         /* root directory */
  442.         if (!curproc->euid || (curproc->euid == rxattr.uid)) {
  443.             rxattr.mode = (rxattr.mode & S_IFMT) | mode;
  444.             return 0;
  445.         }
  446.     } else if (IS_FD_DIR(fc)) {
  447.         if (!curproc->euid || (curproc->euid == fdxattr.uid)) {
  448.             fdxattr.mode = (fdxattr.mode & S_IFMT) | mode;
  449.             return 0;
  450.         }
  451.     } else if (!IS_FD_ENTRY(fc)) {
  452.         if (!curproc->euid && (curproc->euid == b->xattr.uid)) {
  453.             b->xattr.mode = (b->xattr.mode & S_IFMT) | mode;
  454.             return 0;
  455.         }
  456.     }
  457.  
  458.     return EACCDN;
  459. }
  460.  
  461. long ARGS_ON_STACK 
  462. nomkdir(dir, name, mode)
  463.     fcookie *dir;
  464.     const char *name;
  465.     unsigned mode;
  466. {
  467.     UNUSED(dir); UNUSED(name);
  468.     UNUSED(mode);
  469.     return EACCDN;
  470. }
  471.  
  472. static long ARGS_ON_STACK 
  473. bios_rmdir(dir, name)
  474.     fcookie *dir;
  475.     const char *name;
  476. {
  477.     return bios_remove(dir, name);
  478. }
  479.  
  480. /*
  481.  * MAJOR BUG: we don't check here for removal of devices for which there
  482.  * are still open files
  483.  */
  484.  
  485. static long ARGS_ON_STACK 
  486. bios_remove(dir, name)
  487.     fcookie *dir;
  488.     const char *name;
  489. {
  490.     struct bios_file *b, **lastb;
  491.  
  492.     UNUSED(dir);
  493.  
  494.     if (curproc->euid)
  495.         return EACCDN;
  496.  
  497. /* don't allow removal in the fd directory */
  498.     if (IS_FD_DIR(dir))
  499.         return EACCDN;
  500.  
  501.     lastb = &broot;
  502.     for (b = broot; b; b = *(lastb = &b->next)) {
  503.         if (!stricmp(b->name, name)) break;
  504.     }
  505.     if (!b) return EFILNF;
  506.  
  507. /* don't allow removal of the device if we don't own it */
  508.     if (curproc->euid && (curproc->euid != b->xattr.uid)) {
  509.         return EACCDN;
  510.     }
  511.  
  512. /* don't allow removal of the basic system devices */
  513.     if (b >= BDEV && b <= bdevlast) {
  514.         return EACCDN;
  515.     }
  516.     *lastb = b->next;
  517.  
  518.     if (b->device == 0 || b->device == &bios_tdevice)
  519.         kfree(b->tty);
  520.  
  521.     kfree(b);
  522.     return 0;
  523. }
  524.  
  525. static long ARGS_ON_STACK 
  526. bios_getname(root, dir, pathname, size)
  527.     fcookie *root, *dir; char *pathname;
  528.     int size;
  529. {
  530.     char *foo;
  531.  
  532.     if (size == 0)
  533.       return ERANGE;
  534.     if (root->index == dir->index) {
  535.         *pathname = 0;
  536.         return 0;
  537.     }
  538.     /* DIR must point to the fd directory */
  539.     if (!IS_FD_DIR (dir))
  540.         return EINTRN;
  541.     *pathname++ = '\\';
  542.     size--;
  543.     foo = ((struct bios_file *)dir->index)->name;
  544.     if (strlen(foo) < size)
  545.         strcpy(pathname, foo);
  546.     else
  547.         return ERANGE;
  548.     return 0;
  549. }
  550.  
  551. static long ARGS_ON_STACK 
  552. bios_rename(olddir, oldname, newdir, newname)
  553.     fcookie *olddir;
  554.     char *oldname;
  555.     fcookie *newdir;
  556.     const char *newname;
  557. {
  558.     struct bios_file *b, *be = 0;
  559.  
  560.     UNUSED(olddir); UNUSED(newdir);
  561.  
  562.     if (curproc->euid)
  563.         return EACCDN;
  564.  
  565.     for (b = broot; b; b = b->next) {
  566.         if (!stricmp(b->name, newname)) {
  567.             return EACCDN;
  568.         }
  569.         if (!stricmp(b->name, oldname)) {
  570.             be = b;
  571.         }
  572.     }
  573.     if (be) {
  574.         strncpy(be->name, newname, BNAME_MAX);
  575.         return 0;
  576.     }
  577.     return EFILNF;
  578. }
  579.  
  580. static long ARGS_ON_STACK 
  581. bios_opendir(dirh, flags)
  582.     DIR *dirh;
  583.     int flags;
  584. {
  585.     UNUSED(flags);
  586.  
  587.     if (dirh->fc.index != 0 && !IS_FD_DIR(&dirh->fc)) {
  588.         DEBUG(("bios_opendir: bad directory"));
  589.         return EPTHNF;
  590.     }
  591.     return 0;
  592. }
  593.  
  594. static long ARGS_ON_STACK 
  595. bios_readdir(dirh, name, namelen, fc)
  596.     DIR *dirh;
  597.     char *name;
  598.     int namelen;
  599.     fcookie *fc;
  600. {
  601.     struct bios_file *b;
  602.     int giveindex = dirh->flags == 0;
  603.     int i;
  604.     char buf[5];
  605.  
  606.     if (IS_FD_DIR(&dirh->fc)) {
  607.         i = dirh->index++;
  608.         if (i+MIN_HANDLE >= MAX_OPEN)
  609.             return ENMFIL;
  610.         fc->fs = &bios_filesys;
  611.         fc->index = i+1;
  612.         fc->aux = i+MIN_HANDLE;
  613.         fc->dev = dirh->fc.dev;
  614.         if (giveindex) {
  615.             namelen -= (int)sizeof(long);
  616.             if (namelen <= 0)
  617.                 return ERANGE;
  618.             *(long *)name = (long)i + 1;
  619.             name += sizeof(long);
  620.         }
  621.         ksprintf(buf, "%d", i+MIN_HANDLE);
  622.         strncpy(name, buf, namelen - 1);
  623.         if (strlen(buf) >= namelen)
  624.             return ENAMETOOLONG;
  625.         return 0;
  626.     }
  627.  
  628.     b = broot;
  629.     i = dirh->index++;
  630.     while(i-- > 0) {
  631.         if (!b) break;
  632.         b = b->next;
  633.     }
  634.     if (!b) {
  635.         return ENMFIL;
  636.     }
  637.     fc->fs = &bios_filesys;
  638.     fc->index = (long)b;
  639.     fc->aux = b->private;
  640.     fc->dev = dirh->fc.dev;
  641.     if (giveindex) {
  642.         namelen -= (int)sizeof(long);
  643.         if (namelen <= 0)
  644.             return ERANGE;
  645.         *((long *)name) = (long) b;
  646.         name += sizeof(long);
  647.     }
  648.     strncpy(name, b->name, namelen-1);
  649.     if (strlen(b->name) >= namelen)
  650.         return ENAMETOOLONG;
  651.     return 0;
  652. }
  653.  
  654. static long ARGS_ON_STACK 
  655. bios_rewinddir(dirh)
  656.     DIR *dirh;
  657. {
  658.     dirh->index = 0;
  659.     return 0;
  660. }
  661.  
  662. static long ARGS_ON_STACK 
  663. bios_closedir(dirh)
  664.     DIR *dirh;
  665. {
  666.     UNUSED(dirh);
  667.     return 0;
  668. }
  669.  
  670. static long ARGS_ON_STACK 
  671. bios_pathconf(dir, which)
  672.     fcookie *dir;
  673.     int which;
  674. {
  675.     UNUSED(dir);
  676.  
  677.     switch(which) {
  678.     case -1:
  679.         return DP_MAXREQ;
  680.     case DP_IOPEN:
  681.         return UNLIMITED;    /* no limit on BIOS file descriptors */
  682.     case DP_MAXLINKS:
  683.         return 1;        /* no hard links available */
  684.     case DP_PATHMAX:
  685.         return PATH_MAX;
  686.     case DP_NAMEMAX:
  687.         return BNAME_MAX;
  688.     case DP_ATOMIC:
  689.         return 1;        /* no atomic writes */
  690.     case DP_TRUNC:
  691.         return DP_AUTOTRUNC;    /* names are truncated */
  692.     case DP_CASE:
  693.         return DP_CASEINSENS;    /* not case sensitive */
  694.     default:
  695.         return EINVFN;
  696.     }
  697. }
  698.  
  699. static long ARGS_ON_STACK 
  700. bios_dfree(dir, buf)
  701.     fcookie *dir;
  702.     long *buf;
  703. {
  704.     UNUSED(dir);
  705.  
  706.     buf[0] = 0;    /* number of free clusters */
  707.     buf[1] = 0;    /* total number of clusters */
  708.     buf[2] = 1;    /* sector size (bytes) */
  709.     buf[3] = 1;    /* cluster size (sectors) */
  710.     return 0;
  711. }
  712.  
  713. /*
  714.  * BIOS Dcntl() calls:
  715.  * Dcntl(0xde02, "U:\DEV\FOO", &foo_descr): install a new device called
  716.  *     "FOO", which is described by the dev_descr structure "foo_descr".
  717.  *     this structure has the following fields:
  718.  *         DEVDRV *driver        the device driver itself
  719.  *       short  dinfo            info for the device driver
  720.  *       short  flags            flags for the file (e.g. O_TTY)
  721.  *       struct tty *tty        tty structure, if appropriate
  722.  *
  723.  * Dcntl(0xde00, "U:\DEV\BAR", n): install a new BIOS terminal device, with
  724.  *     BIOS device number "n".
  725.  * Dcntl(0xde01, "U:\DEV\BAR", n): install a new non-tty BIOS device, with
  726.  *     BIOS device number "n".
  727.  */
  728.  
  729. static long ARGS_ON_STACK 
  730. bios_fscntl(dir, name, cmd, arg)
  731.     fcookie *dir;
  732.     const char *name;
  733.     int cmd;
  734.     long arg;
  735. {
  736.     struct bios_file *b;
  737.     static int devindex = 0;
  738.  
  739.     UNUSED(dir);
  740.  
  741.     if (curproc->euid) {
  742.         DEBUG(("biosfs: Dcntl() by non-privileged process"));
  743.         return ((unsigned)cmd == DEV_INSTALL) ? 0 : EACCDN;
  744.     }
  745.  
  746.     if (IS_FD_DIR(dir))
  747.         return EACCDN;
  748.  
  749.     if ((unsigned)cmd == DEV_INSTALL) {
  750.         struct dev_descr *d = (struct dev_descr *)arg;
  751.  
  752.         b = kmalloc(SIZEOF(struct bios_file));
  753.         if (!b) return 0;
  754.         strncpy(b->name, name, BNAME_MAX);
  755.         b->name[BNAME_MAX] = 0;
  756.         b->device = d->driver;
  757.         b->private = d->dinfo;
  758.         b->flags = d->flags;
  759.         b->tty = d->tty;
  760.         b->next = broot;
  761.         broot = b;
  762.         set_xattr(&(b->xattr), S_IFCHR|DEFAULT_MODE, UNK_RDEV|devindex);
  763.         devindex = (devindex+1) & 0x00ff;
  764.         return (long)&kernelinfo;
  765.     }
  766.     if ((unsigned)cmd == DEV_NEWTTY) {
  767.         b = kmalloc(SIZEOF(struct bios_file));
  768.         if (!b) return ENSMEM;
  769.         b->tty = kmalloc(SIZEOF(struct tty));
  770.         if (!b->tty) {
  771.             kfree(b);
  772.             return ENSMEM;
  773.         }
  774.         strncpy(b->name, name, BNAME_MAX);
  775.         b->name[BNAME_MAX] = 0;
  776.         b->device = &bios_tdevice;
  777.         b->private = arg;
  778.         b->flags = O_TTY;
  779.         *b->tty = default_tty;
  780.         b->next = broot;
  781.         broot = b;
  782.         set_xattr(&(b->xattr), S_IFCHR|DEFAULT_MODE, BIOS_RDEV|(b->private&0x00ff));
  783.         return 0;
  784.     }
  785.     if ((unsigned)cmd == DEV_NEWBIOS) {
  786.         b = kmalloc(SIZEOF(struct bios_file));
  787.         if (!b) return ENSMEM;
  788.         strncpy(b->name, name, BNAME_MAX);
  789.         b->name[BNAME_MAX] = 0;
  790.         b->tty = 0;
  791.         b->device = &bios_ndevice;
  792.         b->private = arg;
  793.         b->flags = 0;
  794.         b->next = broot;
  795.         broot = b;
  796.         set_xattr(&(b->xattr), S_IFCHR|DEFAULT_MODE, BIOS_RDEV|(b->private&0x00ff));
  797.         return 0;
  798.     }
  799.     return EINVFN;
  800. }
  801.  
  802. static long ARGS_ON_STACK 
  803. bios_symlink(dir, name, to)
  804.     fcookie *dir;
  805.     const char *name, *to;
  806. {
  807.     struct bios_file *b;
  808.     long r;
  809.     fcookie fc;
  810.  
  811.     if (curproc->euid)
  812.         return EACCDN;
  813.  
  814.     r = bios_lookup(dir, name, &fc);
  815.     if (r == 0) return EACCDN;    /* file already exists */
  816.     if (r != EFILNF) return r;    /* some other error */
  817.  
  818.     b = kmalloc(SIZEOF(struct bios_file));
  819.     if (!b) return EACCDN;
  820.  
  821.     strncpy(b->name, name, BNAME_MAX);
  822.     b->name[BNAME_MAX] = 0;
  823.     b->device = 0;
  824.     b->private = EINVFN;
  825.     b->flags = 0;
  826.     b->tty = kmalloc((long)strlen(to)+1);
  827.     if (!b->tty) {
  828.         kfree(b);
  829.         return EACCDN;
  830.     }
  831.     strcpy((char *)b->tty, to);
  832.  
  833.     set_xattr(&b->xattr, S_IFLNK|DEFAULT_DIRMODE, BIOSDRV);
  834.     b->xattr.size = strlen(to)+1;
  835.  
  836.     b->next = broot;
  837.     broot = b;
  838.     return 0;
  839. }
  840.  
  841. static long ARGS_ON_STACK 
  842. bios_readlink(fc, buf, buflen)
  843.     fcookie *fc;
  844.     char *buf;
  845.     int buflen;
  846. {
  847.     struct bios_file *b = (struct bios_file *)fc->index;
  848.  
  849.     if (IS_FD_DIR(fc) || IS_FD_ENTRY(fc))
  850.         return EINVFN;
  851.     if (!b) return EINVFN;
  852.     if (b->device) return EINVFN;
  853.  
  854.     strncpy(buf, (char *)b->tty, buflen);
  855.     if (strlen((char *)b->tty) >= buflen)
  856.         return ENAMETOOLONG;
  857.     return 0;
  858. }
  859.  
  860.  
  861. /*
  862.  * routines for file systems that don't support volume labels
  863.  */
  864.  
  865. long ARGS_ON_STACK 
  866. nowritelabel(dir, name)
  867.     fcookie *dir;
  868.     const char *name;
  869. {
  870.     UNUSED(dir);
  871.     UNUSED(name);
  872.     return EACCDN;
  873. }
  874.  
  875. long ARGS_ON_STACK 
  876. noreadlabel(dir, name, namelen)
  877.     fcookie *dir;
  878.     char *name;
  879.     int namelen;
  880. {
  881.     UNUSED(dir);
  882.     UNUSED(name);
  883.     UNUSED(namelen);
  884.     return EFILNF;
  885. }
  886.  
  887. /*
  888.  * routines for file systems that don't support links
  889.  */
  890.  
  891. long ARGS_ON_STACK 
  892. nosymlink(dir, name, to)
  893.     fcookie *dir;
  894.     const char *name, *to;
  895. {
  896.     UNUSED(dir); UNUSED(name);
  897.     UNUSED(to);
  898.     return EINVFN;
  899. }
  900.  
  901. long ARGS_ON_STACK 
  902. noreadlink(dir, buf, buflen)
  903.     fcookie *dir;
  904.     char *buf;
  905.     int buflen;
  906. {
  907.     UNUSED(dir); UNUSED(buf);
  908.     UNUSED(buflen);
  909.     return EINVFN;
  910. }
  911.  
  912. long ARGS_ON_STACK 
  913. nohardlink(fromdir, fromname, todir, toname)
  914.     fcookie *fromdir, *todir;
  915.     const char *fromname, *toname;
  916. {
  917.     UNUSED(fromdir); UNUSED(todir);
  918.     UNUSED(fromname); UNUSED(toname);
  919.     return EINVFN;
  920. }
  921.  
  922. /* dummy routine for file systems with no Fscntl commands */
  923.  
  924. long ARGS_ON_STACK 
  925. nofscntl(dir, name, cmd, arg)
  926.     fcookie *dir;
  927.     const char *name;
  928.     int cmd;
  929.     long arg;
  930. {
  931.     UNUSED(dir); UNUSED(name);
  932.     UNUSED(cmd); UNUSED(arg);
  933.     return EINVFN;
  934. }
  935.  
  936. /*
  937.  * Did the disk change? Not on this drive!
  938.  * However, we have to do Getbpb anyways, because someone has decided
  939.  * to force a media change on our (non-existent) drive.
  940.  */
  941. long ARGS_ON_STACK 
  942. nodskchng(drv)
  943.     int drv;
  944. {
  945.     (void)getbpb(drv);
  946.     return 0;
  947. }
  948.  
  949. long ARGS_ON_STACK 
  950. nocreat(dir, name, mode, attrib, fc)
  951.     fcookie *dir, *fc;
  952.     const char *name;
  953.     unsigned mode;
  954.     int attrib;
  955. {
  956.     UNUSED(dir); UNUSED(fc);
  957.     UNUSED(name); UNUSED(mode);
  958.     UNUSED(attrib);
  959.     return EACCDN;
  960. }
  961.  
  962. static DEVDRV * ARGS_ON_STACK 
  963. bios_getdev(fc, devsp)
  964.     fcookie *fc;
  965.     long *devsp;
  966. {
  967.     struct bios_file *b;
  968.  
  969.     /* Check for \dev\fd\... */
  970.     if (IS_FD_ENTRY(fc)) {
  971.         *devsp = (int) fc->aux;
  972.         return &fakedev;
  973.     }
  974.  
  975.     b = (struct bios_file *)fc->index;
  976.  
  977.     if (b->device && b->device != &fakedev)
  978.         *devsp = (long)b->tty;
  979.     else
  980.         *devsp = b->private;
  981.  
  982.     return b->device;    /* return the device driver */
  983. }
  984.  
  985. /*
  986.  * NULL device driver
  987.  */
  988.  
  989. long ARGS_ON_STACK 
  990. null_open(f)
  991.     FILEPTR *f;
  992. {
  993.     UNUSED(f);
  994.     return 0;
  995. }
  996.  
  997. long ARGS_ON_STACK 
  998. null_write(f, buf, bytes)
  999.     FILEPTR *f; const char *buf; long bytes;
  1000. {
  1001.     UNUSED(f); UNUSED(buf);
  1002.     return bytes;
  1003. }
  1004.  
  1005. long ARGS_ON_STACK 
  1006. null_read(f, buf, bytes)
  1007.     FILEPTR *f; char *buf; long bytes;
  1008. {
  1009.     UNUSED(f); UNUSED(buf);
  1010.     UNUSED(bytes);
  1011.     return 0;
  1012. }
  1013.  
  1014. long ARGS_ON_STACK 
  1015. null_lseek(f, where, whence)
  1016.     FILEPTR *f; long where; int whence;
  1017. {
  1018.     UNUSED(f); UNUSED(whence);
  1019.     return (where == 0) ? 0 : ERANGE;
  1020. }
  1021.  
  1022. long ARGS_ON_STACK 
  1023. null_ioctl(f, mode, buf)
  1024.     FILEPTR *f; int mode; void *buf;
  1025. {
  1026.     UNUSED(f);
  1027.     if (mode == FIONREAD) {
  1028.         *((long *)buf) = 0;
  1029.     }
  1030.     else if (mode == FIONWRITE)
  1031.         *((long *)buf) = 1;
  1032.     else
  1033.         return EINVFN;
  1034.     return 0;
  1035. }
  1036.  
  1037. long ARGS_ON_STACK 
  1038. null_datime(f, timeptr, rwflag)
  1039.     FILEPTR *f;
  1040.     short *timeptr;
  1041.     int rwflag;
  1042. {
  1043.     UNUSED(f);
  1044.     if (rwflag)
  1045.         return EACCDN;
  1046.     *timeptr++ = timestamp;
  1047.     *timeptr = datestamp;
  1048.     return 0;
  1049. }
  1050.  
  1051. long ARGS_ON_STACK 
  1052. null_close(f, pid)
  1053.     FILEPTR *f;
  1054.     int pid;
  1055. {
  1056.     UNUSED(f);
  1057.     UNUSED(pid);
  1058.     return 0;
  1059. }
  1060.  
  1061. long ARGS_ON_STACK 
  1062. null_select(f, p, mode)
  1063.     FILEPTR *f; long p;
  1064.     int mode;
  1065. {
  1066.     UNUSED(f); UNUSED(p);
  1067.     UNUSED(mode);
  1068.     return 1;    /* we're always ready to read/write */
  1069. }
  1070.  
  1071. void ARGS_ON_STACK 
  1072. null_unselect(f, p, mode)
  1073.     FILEPTR *f;
  1074.     long p;
  1075.     int mode;
  1076. {
  1077.     UNUSED(f); UNUSED(p);
  1078.     UNUSED(mode);
  1079.     /* nothing to do */
  1080. }
  1081.  
  1082. /*
  1083.  * BIOS terminal device driver
  1084.  */
  1085.  
  1086. static long ARGS_ON_STACK 
  1087. bios_topen(f)
  1088.     FILEPTR *f;
  1089. {
  1090.     f->flags |= O_TTY;
  1091.     return 0;
  1092. }
  1093.  
  1094. /*
  1095.  * Note: when a BIOS device is a terminal (i.e. has the O_TTY flag
  1096.  * set), bios_read and bios_write will only ever be called indirectly, via
  1097.  * tty_read and tty_write. That's why we can afford to play a bit fast and
  1098.  * loose with the pointers ("buf" is really going to point to a long) and
  1099.  * why we know that "bytes" is divisible by 4.
  1100.  */
  1101.  
  1102. static long ARGS_ON_STACK 
  1103. bios_twrite(f, buf, bytes)
  1104.     FILEPTR *f; const char *buf; long bytes;
  1105. {
  1106.     long *r;
  1107.     long ret = 0;
  1108.     int bdev = f->fc.aux;
  1109.     struct bios_file *b = (struct bios_file *)f->fc.index;
  1110.  
  1111.     r = (long *)buf;
  1112.  
  1113. /* Check for control characters on any newline output.
  1114.  * Note that newlines are always output through tty_putchar,
  1115.  * so they'll always be the first thing in the buffer (at least,
  1116.  * for cooked TTY output they will, which is the only sort that
  1117.  * control characters affect anyways).
  1118.  */
  1119.     if (bytes > 0 && (*r & 0x000000ffL) == '\n')
  1120.         (void) checkkeys();
  1121.  
  1122.     if (f->flags & O_NDELAY) {
  1123.         while (bytes > 0) {
  1124.             if (!bcostat(bdev)) break;
  1125.             if (bconout(bdev, (int)*r) == 0)
  1126.             break;
  1127.             r++; bytes -= 4; ret+= 4;
  1128.         }
  1129.     } else {
  1130.         while (bytes > 0) {
  1131.             if (bconout(bdev, (int)*r) == 0)
  1132.             break;
  1133.             r++; bytes -= 4; ret+= 4;
  1134.         }
  1135.     }
  1136.  
  1137.     if (ret > 0) {
  1138.         b->xattr.mtime = b->xattr.atime = timestamp;
  1139.         b->xattr.mdate = b->xattr.adate = datestamp;
  1140.     }
  1141.     return ret;
  1142. }
  1143.  
  1144. static long ARGS_ON_STACK 
  1145. bios_tread(f, buf, bytes)
  1146.     FILEPTR *f; char *buf; long bytes;
  1147. {
  1148.     long *r, ret = 0;
  1149.     int bdev = f->fc.aux;
  1150.     struct  bios_file *b = (struct bios_file *)f->fc.index;
  1151.  
  1152.     r = (long *)buf;
  1153.  
  1154.     if ((f->flags & O_NDELAY)) {
  1155.         while (bytes > 0) {
  1156.             if ( !bconstat(bdev) )
  1157.             break;
  1158.             *r++ = bconin(bdev) & 0x7fffffffL;
  1159.             bytes -= 4; ret += 4;
  1160.         }
  1161.     } else {
  1162.         while (bytes > 0) {
  1163.             *r++ = bconin(bdev) & 0x7fffffffL;
  1164.             bytes -= 4; ret += 4;
  1165.         }
  1166.     }
  1167.     if (ret > 0) {
  1168.         b->xattr.atime = timestamp;
  1169.         b->xattr.adate = datestamp;
  1170.     }
  1171.     return ret;
  1172. }
  1173.  
  1174. /*
  1175.  * read/write routines for BIOS devices that aren't terminals (like the
  1176.  * printer & IKBD devices)
  1177.  */
  1178.  
  1179. static long ARGS_ON_STACK 
  1180. bios_nwrite(f, buf, bytes)
  1181.     FILEPTR *f; const char *buf; long bytes;
  1182. {
  1183.     long ret = 0;
  1184.     int bdev = f->fc.aux;
  1185.     int c;
  1186.     struct bios_file *b = (struct bios_file *)f->fc.index;
  1187.  
  1188.     while (bytes > 0) {
  1189.         if ( (f->flags & O_NDELAY) && !bcostat(bdev) )
  1190.             break;
  1191.  
  1192.         c = *buf++ & 0x00ff;
  1193.  
  1194.         if (bconout(bdev, c) == 0)
  1195.             break;
  1196.  
  1197.         bytes--; ret++;
  1198.     }
  1199.     if (ret > 0) {
  1200.         b->xattr.mtime = b->xattr.atime = timestamp;
  1201.         b->xattr.mdate = b->xattr.adate = datestamp;
  1202.     }
  1203.     return ret;
  1204. }
  1205.  
  1206. static long ARGS_ON_STACK 
  1207. bios_nread(f, buf, bytes)
  1208.     FILEPTR *f; char *buf; long bytes;
  1209. {
  1210.     long ret = 0;
  1211.     int bdev = f->fc.aux;
  1212.     struct bios_file *b = (struct bios_file *)f->fc.index;
  1213.  
  1214.     while (bytes > 0) {
  1215.         if ( (f->flags & O_NDELAY) && !bconstat(bdev) )
  1216.             break;
  1217.         *buf++ = bconin(bdev) & 0xff;
  1218.         bytes--; ret++;
  1219.     }
  1220.     if (ret > 0) {
  1221.         b->xattr.atime = timestamp;
  1222.         b->xattr.adate = datestamp;
  1223.     }
  1224.     return ret;
  1225. }
  1226.  
  1227. /*
  1228.  * BIOS terminal seek code -- this has to match the documented
  1229.  * way to do isatty()
  1230.  */
  1231.  
  1232. static long ARGS_ON_STACK 
  1233. bios_tseek(f, where, whence)
  1234.     FILEPTR *f;
  1235.     long where;
  1236.     int whence;
  1237. {
  1238.     UNUSED(f); UNUSED(where);
  1239.     UNUSED(whence);
  1240. /* terminals always are at position 0 */
  1241.     return 0;
  1242. }
  1243.  
  1244. #define MAXBAUD 16
  1245.  
  1246. /* keep these sorted in descending order */
  1247. static long baudmap[MAXBAUD] = {
  1248. 19200L, 9600L, 4800L, 3600L, 2400L, 2000L, 1800L, 1200L,
  1249. 600L, 300L, 200L, 150L, 134L, 110L, 75L, 50L
  1250. };
  1251.  
  1252. static long ARGS_ON_STACK 
  1253. bios_ioctl(f, mode, buf)
  1254.     FILEPTR *f; int mode; void *buf;
  1255. {
  1256.     long *r = (long *)buf;
  1257.     struct winsize *ws;
  1258.     char *aline;
  1259.     short dev;
  1260.     int i;
  1261.     struct bios_file *b;
  1262.  
  1263.     if (mode == FIONREAD) {
  1264.         if (bconstat(f->fc.aux))
  1265.             *r = 1;
  1266.         else
  1267.             *r = 0;
  1268.     }
  1269.     else if (mode == FIONWRITE) {
  1270.         if (bcostat(f->fc.aux))
  1271.             *r = 1;
  1272.         else
  1273.             *r = 0;
  1274.     }
  1275.     else if (mode == TIOCFLUSH) {
  1276.         int oldmap;
  1277.         IOREC_T *ior;
  1278.         int flushtype;
  1279.         short sr;
  1280.  
  1281.         dev = f->fc.aux;
  1282.  
  1283.         if ((!r) || (!(*r & 3))) {
  1284.             flushtype = 3;
  1285.         } else {
  1286.             flushtype = (int) *r;
  1287.         }
  1288.         if (dev == 1 || dev >= 6) {
  1289. /* trick uiorec into setting the correct port (it uses curproc->bconmap) */
  1290.             oldmap = curproc->bconmap;
  1291.             if (has_bconmap)
  1292.                 curproc->bconmap = (dev == 1)
  1293.                         ? curproc->bconmap
  1294.                         : dev;
  1295.             ior = (IOREC_T *) uiorec(0);
  1296.             if (flushtype & 1) {
  1297.                 sr = spl7();
  1298.                 ior->head = ior->tail = 0;
  1299.                 spl(sr);
  1300.             }
  1301.             if (flushtype & 2) {
  1302.                 ior++; /* output record */
  1303.                 sr = spl7();
  1304.                 ior->head = ior->tail = 0;
  1305.                 spl(sr);
  1306.             }
  1307.             curproc->bconmap = oldmap;
  1308.         } else if (dev == 3 || dev == 2 || dev == 5) {
  1309.             if (dev == 3) {
  1310.                 /* midi */
  1311.                 ior = (IOREC_T *) uiorec(2);
  1312.             } else {
  1313.                 /* ikbd */
  1314.                 ior = (IOREC_T *) uiorec(1);
  1315.             }
  1316.             if (flushtype & 1) {
  1317.                 sr = spl7();
  1318.                 ior->head = ior->tail = 0;
  1319.                 spl(sr);
  1320.             }
  1321.         }
  1322.         return 0;
  1323.     }
  1324.     else if (mode == TIOCOUTQ) {
  1325.         int oldmap;
  1326.         IOREC_T *ior;
  1327.  
  1328.         dev = f->fc.aux;
  1329.  
  1330.         if (dev == 1 || dev >= 6) {
  1331. /* trick uiorec into setting the correct port (it uses curproc->bconmap) */
  1332.             oldmap = curproc->bconmap;
  1333.             if (has_bconmap)
  1334.                 curproc->bconmap = (dev == 1)
  1335.                         ? curproc->bconmap
  1336.                         : dev;
  1337.             ior = (IOREC_T *) uiorec(0) + 1;
  1338.             *r = ior->tail - ior->head;
  1339.             if (*r < 0)
  1340.                 *r += ior->buflen;
  1341.             curproc->bconmap = oldmap;
  1342.         }
  1343.          else
  1344.             *r = 0;
  1345.         return 0;
  1346.     }
  1347.     else if (mode == TIOCGWINSZ && f->fc.aux == 2) {
  1348.         aline = lineA0();
  1349.         ws = (struct winsize *)buf;
  1350.         ws->ws_row = *((short *)(aline - 42)) + 1;
  1351.         ws->ws_col = *((short *)(aline - 44)) + 1;
  1352.     } else if (mode == TIOCIBAUD || mode == TIOCOBAUD) {
  1353.         long oldbaud, newbaud;
  1354.         int oldmap;
  1355.  
  1356.         dev = f->fc.aux;
  1357.  
  1358.         newbaud = *r;
  1359.         if (dev == 1 || dev >= 6) {
  1360. /* trick rsconf into setting the correct port (it uses curproc->bconmap) */
  1361.             oldmap = curproc->bconmap;
  1362.             if (has_bconmap)
  1363.                 curproc->bconmap = 
  1364.                     (dev == 1) ? curproc->bconmap : dev;
  1365.             i = (int)rsconf(-2, -1, -1, -1, -1, -1);
  1366.  
  1367.             if (i < 0 || i >= MAXBAUD)
  1368.                 oldbaud = -1L;
  1369.             else
  1370.                 oldbaud = baudmap[i];
  1371.             *r = oldbaud;
  1372.             if (newbaud > 0) {
  1373.     /* BUG: assert DTR works only on modem1 */
  1374.                 if (dev == 1 || dev == 6) {
  1375.                     Offgibit(0xef);
  1376.                 }
  1377.                 if (newbaud == oldbaud) {
  1378.                     curproc->bconmap = oldmap;
  1379.                     return 0;
  1380.                 }
  1381.                 for (i = 0; i < MAXBAUD; i++) {
  1382.                     if (baudmap[i] == newbaud) {
  1383.                         rsconf(i, -1, -1, -1, -1, -1);
  1384.                         curproc->bconmap = oldmap;
  1385.                         return 0;
  1386.                     } else if (baudmap[i] < newbaud) {
  1387.                         *r = baudmap[i];
  1388.                         curproc->bconmap = oldmap;
  1389.                         break;
  1390.                     }
  1391.                 }
  1392.                 curproc->bconmap = oldmap;
  1393.                 return ERANGE;
  1394.             } else if (newbaud == 0L) {
  1395.     /* BUG: drop DTR: works only on modem1 */
  1396.                 if (dev == 1 || dev == 6) {
  1397.                     Ongibit(0x10);
  1398.                 }
  1399.             }
  1400.             curproc->bconmap = oldmap;
  1401.             return 0;
  1402.         } else if (dev == 2 || dev == 5) {
  1403.             /* screen: assume 9600 baud */
  1404.             oldbaud = 9600L;
  1405.         } else if (dev == 3) {
  1406.             /* midi */
  1407.             oldbaud = 31250L;
  1408.         } else {
  1409.             oldbaud = -1L;    /* unknown speed */
  1410.         }
  1411.         *r = oldbaud;
  1412.         if (newbaud > 0 && newbaud != oldbaud)
  1413.             return ERANGE;
  1414.         return 0;
  1415.     } else if (mode == TIOCCBRK || mode == TIOCSBRK) {
  1416.         unsigned long bits;
  1417.  
  1418.         dev = f->fc.aux;
  1419.         if (dev == 1 || dev >= 6) {
  1420.             if (has_bconmap)
  1421.                 mapin((dev == 1) ? curproc->bconmap : dev);
  1422.         } else {
  1423.             return EINVFN;
  1424.         }
  1425.         bits = rsconf(-1, -1, -1, -1, -1, -1);    /* get settings */
  1426.         bits = (bits >> 8) & 0x0ff;        /* isolate TSR byte */
  1427.         if (mode == TIOCCBRK)
  1428.             bits &= ~8;
  1429.         else
  1430.             bits |= 8;
  1431.         (void)rsconf(-1, -1, -1, -1, (int)bits, -1);
  1432.     } else if (mode == TIOCGFLAGS || mode == TIOCSFLAGS) {
  1433.         unsigned short oflags, flags, *sgflags;
  1434.         unsigned long bits;
  1435.         unsigned char ucr;
  1436.         short flow;
  1437.  
  1438.         dev = f->fc.aux;
  1439.         if (dev == 1 || dev >= 6) {
  1440.             sgflags = &((struct tty *)f->devinfo)->sg.sg_flags;
  1441.             oflags = *sgflags & (T_TANDEM|T_RTSCTS);
  1442.             if (has_bconmap)
  1443.                 mapin((dev == 1) ? curproc->bconmap : dev);
  1444.             bits = rsconf(-1, -1, -1, -1, -1, -1);    /* get settings */
  1445.             ucr = (bits >> 24L) & 0x0ff;        /* isolate UCR byte */
  1446.             oflags |= (ucr >> 3) & (TF_STOPBITS|TF_CHARBITS);
  1447.             if (ucr & 0x4) {            /* parity on? */
  1448.                 oflags |= (ucr & 0x2) ? T_EVENP : T_ODDP;
  1449.             }
  1450.             if (mode == TIOCSFLAGS) {
  1451.                 flags = (*(unsigned short *)buf);
  1452.                 *sgflags &= ~(T_RTSCTS|T_TANDEM);
  1453.                 *sgflags |= flags & (T_RTSCTS|T_TANDEM);
  1454.                 if (flags & T_EVENP) {
  1455.                     ucr |= 0x6;
  1456.                 } else if (flags & T_ODDP) {
  1457.                     ucr &= ~2;
  1458.                     ucr |= 0x4;
  1459.                 } else {
  1460.                     ucr &= ~6;
  1461.                 }
  1462.                 if (flags & TF_STOPBITS) {
  1463.                     ucr &= ~(0x18);
  1464.                     ucr |= (flags & TF_STOPBITS) << 3;
  1465.                 }
  1466.                 ucr &= ~(0x60);
  1467.                 ucr |= (flags & TF_CHARBITS) << 3;
  1468.                 flow = (flags & (T_RTSCTS|T_TANDEM)) >> 12L;
  1469.                 rsconf(-1, flow, ucr, -1, -1, -1);
  1470.             } else {
  1471.                 *((unsigned short *)buf) = oflags;
  1472.             }
  1473.         } else {
  1474.             return EINVFN;
  1475.         }
  1476.     } else if ((mode >= TCURSOFF && mode <= TCURSSTEADY) && (f->fc.aux == 2)) {
  1477.         return Cursconf(mode - TCURSOFF, 0);
  1478.     } else if ((mode >= TCURSSRATE && mode <= TCURSGRATE) && (f->fc.aux == 2)) {
  1479.         long r;
  1480.  
  1481.         r = Cursconf(mode - TCURSOFF, *((short *)buf));
  1482.         if (r >= 0) {
  1483.             *(short *)buf = r;
  1484.             r = 0;
  1485.         }
  1486.         return r;
  1487.     } else if (mode == F_SETLK || mode == F_SETLKW) {
  1488.         struct flock *lck = (struct flock *)buf;
  1489.  
  1490.         b = (struct bios_file *)f->fc.index;
  1491.         while (b->lockpid && b->lockpid != curproc->pid) {
  1492.             if (mode == F_SETLKW && lck->l_type != F_UNLCK)
  1493.                 sleep(IO_Q, (long)b);
  1494.             else
  1495.                 return ELOCKED;
  1496.         }
  1497.         if (lck->l_type == F_UNLCK) {
  1498.             if (!(f->flags & O_LOCK)) {
  1499.                 DEBUG(("bios_ioctl: wrong file descriptor for UNLCK"));
  1500.                 return ENSLOCK;
  1501.             }
  1502.             if (b->lockpid != curproc->pid)
  1503.                 return ENSLOCK;
  1504.             b->lockpid = 0;
  1505.             f->flags &= ~O_LOCK;
  1506.             wake(IO_Q, (long)b);    /* wake anyone waiting for this lock */
  1507.         } else {
  1508.             b->lockpid = curproc->pid;
  1509.             f->flags |= O_LOCK;
  1510.         }
  1511.     } else if (mode == F_GETLK) {
  1512.         struct flock *lck = (struct flock *)buf;
  1513.  
  1514.         b = (struct bios_file *)f->fc.index;
  1515.         if (b->lockpid) {
  1516.             lck->l_type = F_WRLCK;
  1517.             lck->l_start = lck->l_len = 0;
  1518.             lck->l_pid = b->lockpid;
  1519.         } else {
  1520.             lck->l_type = F_UNLCK;
  1521.         }
  1522.     } else {
  1523.     /* Fcntl will automatically call tty_ioctl to handle
  1524.      * terminal calls that we didn't deal with
  1525.      */
  1526.         return EINVFN;
  1527.     }
  1528.     return 0;
  1529. }
  1530.  
  1531. static long ARGS_ON_STACK 
  1532. bios_select(f, p, mode)
  1533.     FILEPTR *f; long p; int mode;
  1534. {
  1535.     struct tty *tty = (struct tty *)f->devinfo;
  1536.     int dev = f->fc.aux;
  1537.  
  1538.     if (mode == O_RDONLY) {
  1539.         if (bconstat(dev)) {
  1540.             TRACE(("bios_select: data present for device %d", dev));
  1541.             return 1;
  1542.         }
  1543.         if (tty) {
  1544.         /* avoid collisions with other processes */
  1545.             if (!tty->rsel)
  1546.                 return 2;    /* collision */
  1547.             tty->rsel = p;
  1548.         }
  1549.         return 0;
  1550.     } else if (mode == O_WRONLY) {
  1551.         if (bcostat(dev)) {
  1552.             TRACE(("bios_select: ready to output on %d", dev));
  1553.             return 1;
  1554.         }
  1555.         if (tty) {
  1556.             if (!tty->wsel)
  1557.                 return 2;    /* collision */
  1558.             tty->wsel = p;
  1559.         }
  1560.         return 0;
  1561.     }
  1562.     /* default -- we don't know this mode, return 0 */
  1563.     return 0;
  1564. }
  1565.  
  1566. static void ARGS_ON_STACK 
  1567. bios_unselect(f, p, mode)
  1568.     FILEPTR *f;
  1569.     long p;
  1570.     int mode;
  1571. {
  1572.     struct tty *tty = (struct tty *)f->devinfo;
  1573.  
  1574.     if (tty) {
  1575.         if (mode == O_RDONLY && tty->rsel == p)
  1576.             tty->rsel = 0;
  1577.         else if (mode == O_WRONLY && tty->wsel == p)
  1578.             tty->wsel = 0;
  1579.     }
  1580. }
  1581.  
  1582. static long ARGS_ON_STACK 
  1583. bios_close(f, pid)
  1584.     FILEPTR *f;
  1585.     int pid;
  1586. {
  1587.     struct bios_file *b;
  1588.  
  1589.     b = (struct bios_file *)f->fc.index;
  1590.     if ((f->flags & O_LOCK) && (b->lockpid == pid)) {
  1591.         b->lockpid = 0;
  1592.     }
  1593.     return 0;
  1594. }
  1595.  
  1596. /*
  1597.  * mouse device driver
  1598.  */
  1599.  
  1600. #define MOUSESIZ 128*3
  1601. static unsigned char mousebuf[MOUSESIZ];
  1602. static int mousehead, mousetail;
  1603.  
  1604. long mousersel;    /* is someone calling select() on the mouse? */
  1605.  
  1606. char mshift;        /* shift key status; set by checkkeys() in bios.c */
  1607. short *gcurx = 0,
  1608.       *gcury = 0;    /* mouse pos. variables; used by big screen emulators */
  1609.  
  1610. void ARGS_ON_STACK 
  1611. mouse_handler(buf)
  1612.     const char *buf;    /* must be a *signed* character */
  1613. {
  1614.     unsigned char *mbuf, buttons;
  1615.     int newmtail;
  1616.     short dx, dy;
  1617.  
  1618. /* the Sun mouse driver has 0=down, 1=up, while the atari hardware gives
  1619.    us the reverse. also, we have the "middle" button and the "left"
  1620.    button reversed; so we use this table to convert (and also to add the
  1621.    0x80 to indicate a mouse packet)
  1622.  */
  1623.     static int _cnvrt[8] = {
  1624.         0x87, 0x86, 0x83, 0x82, 0x85, 0x84, 0x81, 0x80
  1625.     };
  1626.  
  1627.     mbuf = &mousebuf[mousetail];
  1628.     newmtail = mousetail + 3;
  1629.     if (newmtail >= MOUSESIZ)
  1630.         newmtail = 0;
  1631.     if (newmtail == mousehead)
  1632.         return;            /* buffer full */
  1633.  
  1634.     buttons = *buf++ & 0x7;        /* convert to SUN format */
  1635.     if (mshift & 0x3) {        /* a shift key held down? */
  1636.     /* if so, convert shift+button to a "middle" button */
  1637.         if (buttons == 0x1 || buttons == 0x2)
  1638.             buttons = 0x4;
  1639.         else if (buttons == 0x3)
  1640.             buttons = 0x7;
  1641.     }
  1642.     *mbuf++ = _cnvrt[buttons];    /* convert to Sun format */
  1643.     dx = *buf++;
  1644.     *mbuf++ = dx;            /* copy X delta */
  1645.     dy = *buf;
  1646.     *mbuf = -dy;            /* invert Y delta for Sun format */
  1647.     mousetail = newmtail;
  1648.     *gcurx += dx;            /* update line A variables */
  1649.     *gcury += dy;
  1650. /*
  1651.  * if someone has called select() waiting for mouse input, wake them
  1652.  * up
  1653.  */
  1654.     if (mousersel) {
  1655.         wakeselect(mousersel);
  1656.     }
  1657. }
  1658.  
  1659. extern void newmvec(), newjvec();    /* in intr.s */
  1660. static long oldvec = 0;
  1661. long oldjvec = 0;
  1662.  
  1663. static long ARGS_ON_STACK 
  1664. mouse_open(f)
  1665.     FILEPTR *f;
  1666. {
  1667.     char *aline;
  1668.  
  1669.     static char parameters[] = {
  1670.         0,         /* Y=0 in lower corner */
  1671.         0,        /* normal button handling */
  1672.         1, 1        /* X, Y scaling factors */
  1673.     };
  1674.  
  1675.     UNUSED(f);
  1676.  
  1677.     if (oldvec)        /* mouse in use */
  1678.         return EACCDN;
  1679.  
  1680. /* initialize pointers to line A variables */
  1681.     if (!gcurx) {
  1682.         aline = lineA0();
  1683.         if (aline == 0)    {    /* should never happen */
  1684.             ALERT("unable to read line A variables");
  1685.             return -1;
  1686.         }
  1687.         gcurx = (short *)(aline - 0x25a);
  1688.         gcury = (short *)(aline - 0x258);
  1689.         *gcurx = *gcury = 32;    /* magic number -- what MGR uses */
  1690.     }
  1691.  
  1692.     oldvec = syskey->mousevec;
  1693.     oldjvec = syskey->joyvec;    /* jr: save old joystick vector */
  1694.     Initmous(1, parameters, newmvec);
  1695.     syskey->joyvec = (long)newjvec;    /* jr: set up new joystick handler */
  1696.     mousehead = mousetail = 0;
  1697.     return 0;
  1698. }
  1699.  
  1700. static long ARGS_ON_STACK 
  1701. mouse_close(f, pid)
  1702.     FILEPTR *f;
  1703.     int pid;
  1704. {
  1705.     static char parameters[] = {
  1706.         0,         /* Y=0 in lower corner */
  1707.         0,        /* normal button handling */
  1708.         1, 1        /* X, Y scaling factors */
  1709.     };
  1710.  
  1711.     UNUSED(pid);
  1712.     if (!f) return EIHNDL;
  1713.     if (f->links <= 0) {
  1714.         if (!oldvec) {
  1715.             DEBUG(("Mouse not open!!"));
  1716.             return -1;
  1717.         }
  1718.         Initmous(1, parameters, (void *)oldvec);    /* gratuitous (void *) for Lattice */
  1719.         syskey->joyvec = oldjvec;    /* jr: restore old joystick handler */
  1720.         oldvec = 0;
  1721.     }
  1722.     return 0;
  1723. }
  1724.  
  1725. static long ARGS_ON_STACK 
  1726. mouse_read(f, buf, nbytes)
  1727.     FILEPTR *f;
  1728.     char *buf;
  1729.     long nbytes;
  1730. {
  1731.     long count = 0;
  1732.     int mhead;
  1733.     unsigned char *foo;
  1734.     struct bios_file *b = (struct bios_file *)f->fc.index;
  1735.  
  1736.     mhead = mousehead;
  1737.     foo = &mousebuf[mhead];
  1738.  
  1739.     if (mhead == mousetail) {
  1740.         if (f->flags & O_NDELAY)
  1741.             return 0;
  1742.         do {
  1743.             yield();
  1744.         } while (mhead == mousetail);
  1745.     }
  1746.  
  1747.     while ( (mhead != mousetail) && (nbytes > 0)) {
  1748.         *buf++ = *foo++;
  1749.         mhead++;
  1750.         if (mhead >= MOUSESIZ) {
  1751.             mhead = 0;
  1752.             foo = mousebuf;
  1753.         }
  1754.         count++;
  1755.         --nbytes;
  1756.     }
  1757.     mousehead = mhead;
  1758.     if (count > 0) {
  1759.         b->xattr.atime = timestamp;
  1760.         b->xattr.adate = datestamp;
  1761.     }
  1762.     return count;
  1763. }
  1764.  
  1765. static long ARGS_ON_STACK 
  1766. mouse_ioctl(f, mode, buf)
  1767.     FILEPTR *f;
  1768.     int mode;
  1769.     void *buf;
  1770. {
  1771.     long r;
  1772.  
  1773.     UNUSED(f);
  1774.     if (mode == FIONREAD) {
  1775.         r = mousetail - mousehead;
  1776.         if (r < 0) r += MOUSESIZ;
  1777.         *((long *)buf) = r;
  1778.     }
  1779.     else
  1780.         return EINVFN;
  1781.     return 0;
  1782. }
  1783.  
  1784. static long ARGS_ON_STACK 
  1785. mouse_select(f, p, mode)
  1786.     FILEPTR *f;
  1787.     long p;
  1788.     int mode;
  1789. {
  1790.     UNUSED(f);
  1791.  
  1792.     if (mode != O_RDONLY)
  1793.         return 1;    /* we can always take output :-) */
  1794.  
  1795.     if (mousetail - mousehead)
  1796.         return 1;    /* input waiting already */
  1797.  
  1798.     if (mousersel)
  1799.         return 2;    /* collision */
  1800.     mousersel = p;
  1801.     return 0;
  1802. }
  1803.  
  1804. static void ARGS_ON_STACK 
  1805. mouse_unselect(f, p, mode)
  1806.     FILEPTR *f;
  1807.     long p;
  1808.     int mode;
  1809. {
  1810.     UNUSED(f);
  1811.  
  1812.     if (mode == O_RDONLY && mousersel == p)
  1813.         mousersel = 0;
  1814. }
  1815.  
  1816.  
  1817. /*
  1818.  * UTILITY ROUTINE called by Bconmap() in xbios.c:
  1819.  * this sets handle -1 of process p to a file handle
  1820.  * that has BIOS device "dev". Returns 0 on failure,
  1821.  * non-zero on success.
  1822.  */
  1823.  
  1824. int
  1825. set_auxhandle(p, dev)
  1826.     PROC *p;
  1827.     int dev;
  1828. {
  1829.     FILEPTR *f;
  1830.     struct bios_file *b;
  1831.  
  1832.     f = new_fileptr();
  1833.     if (f) {
  1834.         f->links = 1;
  1835.         f->flags = O_RDWR;
  1836.         f->pos = 0;
  1837.         f->devinfo = 0;
  1838.         f->fc.fs = &bios_filesys;
  1839.         f->fc.aux = dev;
  1840.         f->fc.dev = BIOSDRV;
  1841.         for (b = broot; b; b = b->next) {
  1842.             if (b->private == dev &&
  1843.                 (b->device == &bios_tdevice ||
  1844.                  b->device == &bios_ndevice)) {
  1845.                 f->fc.index = (long)b;
  1846.                 f->dev = b->device;
  1847.                 if (b->device != &fakedev)
  1848.                     f->devinfo = (long)b->tty;
  1849.                 goto found_device;
  1850.             }
  1851.         }
  1852.         f->fc.index = 0;
  1853.         f->dev = &bios_ndevice;
  1854. found_device:
  1855.         if ((*f->dev->open)(f) < 0) {
  1856.             f->links = 0;
  1857.             dispose_fileptr(f);
  1858.             return 0;
  1859.         }
  1860.     } else {
  1861. /* no memory! use the fake FILEPTR we
  1862.  * set up in biosfs_init
  1863.  */
  1864.         f = defaultaux;
  1865.         f->links++;
  1866.     }
  1867.  
  1868.     (void)do_pclose(p, p->aux);
  1869.     p->aux = f;
  1870.  
  1871.     return 1;
  1872. }
  1873.